#include <sstream>
#include "TilesetManager.hpp"
#include "Path.hpp"
#include "Logger.hpp"
#include "DAT.hpp"
#include "ImageManager.hpp"
#include <json/elements.h>
#include <json/reader.h>



Tileset::Tileset(const int widthTile, const int heightTile):
m_widthTile(widthTile),
m_heightTile(heightTile),
m_tiles()
{
}

void Tileset::addTile(ImagePtr t)
{
	m_tiles.push_back(t);
}

ImagePtr Tileset::tile(const unsigned int index)
{
	if(index < m_tiles.size())
		return m_tiles[index];
	else
		ImagePtr();
}
		
void Tileset::setNbTiles(const int nbTiles)
{
	m_tiles.reserve(sizeof(ImagePtr)*nbTiles);
}

unsigned int Tileset::nbTiles()
{
	return m_tiles.size();
}

TilesetManager::TilesetManager()
{
}


TilesetManager::~TilesetManager()
{
}

TilesetManager& TilesetManager::instance()
{
	static TilesetManager tm;
	return tm;
}

bool TilesetManager::loadRessource(RessourceDef& resDef)
{
	
	// check file
	Path p(resDef.m_name);
	if(!p.isValid())
	{
		LogErr << "Unable to load tileset : "<< p.fileName() << ".Reason : this file is not valid." << LogEnd; 
		return false;
	}
		
	// load it
	DAT parserDAT;
	parserDAT.read(resDef.m_name);

	// load info file
	char* infoFile = parserDAT.file("info");
	if(infoFile == NULL)
	{
		LogErr << "Unable to read info file from tileset : " << p.fileName() << "." << LogEnd;
		return false;
	}
	char *temp = new char[parserDAT.fileSize("info")];
	temp = infoFile;
	std::stringstream ss;
	ss << temp;
	json::Object doc;
	json::Reader::Read(doc,ss);
	const json::Object &root = doc;
	const json::Number& jnbFiles = root["nbTiles"];
	const json::Number& jwidth = root["widthTile"];
	const json::Number& jheight = root["heightTile"];

	const unsigned int nbFiles = int(jnbFiles.Value());
	const int widthTile = int(jwidth.Value());
	const int heightTile = int(jheight.Value());
	
	// load image
	sf::Image sourceImage;
	if(!sourceImage.LoadFromMemory(parserDAT.file("source.bmp"),parserDAT.fileSize("source.bmp")))
	{
		LogErr << "Couldn't load source image from tileset:" << p.fileName() << "." << LogEnd;
		return false;
	}
	
	const int nbColumn = sourceImage.GetWidth()/widthTile;
	const int nbRow = sourceImage.GetHeight()/heightTile;
	
	// create tiles
	Tileset *tileset = new Tileset(widthTile,heightTile);
	tileset->setNbTiles(nbFiles);
	for(unsigned int i = 0; i < nbFiles; ++i)
	{
		const int currentIndexX = (i%nbColumn)*widthTile; // 
		const int currentIndexY = (i/nbRow)*heightTile;
		sf::Image *tile=new sf::Image;
		tile->Create(widthTile,heightTile);
		tile->Copy(sourceImage,0,0,sf::IntRect(currentIndexX,currentIndexY,currentIndexX+widthTile,currentIndexY+heightTile));
		tileset->addTile(ImagePtr(tile));
	}

	m_ressources[resDef.m_name] = TilesetPtr(tileset);
	return true;
}



